/**
 * 		-	ad-creatif	-
 * 		-	20/07/2012	-
 *
 * Critical class placing the land, blocks and enemies
 * 
 **/

package {
	
	import blocks.*;
	
	import entities.*;
	
	import flash.display.*;
	import flash.geom.Rectangle;
	
	import org.flixel.FlxBasic;
	import org.flixel.FlxGroup;
	import org.flixel.FlxObject;
	import org.flixel.FlxPoint;
	import org.flixel.FlxTilemap;
	
	import tools.MyFlxTilemap;
	
	
	public class Level extends FlxBasic {
		
		public var ground:MyFlxTilemap;
		public var dynamicMap:MyFlxTilemap;
		public var backgrounds:FlxGroup;
		public var firstgrounds:FlxGroup;
		public var tileSize:Array;
		private var tileMap:MyFlxTilemap;
		private var tileInfo:Object; 
		public var checkpoints:Array;
		
		public function Level() {
			super();
			
			firstgrounds = new FlxGroup;
			backgrounds = new FlxGroup;
			Registry.dynamicPool = new FlxGroup;
			Registry.solidTilesPool = new FlxGroup;
			checkpoints = [];
			
			
			// verify if ground layer exist and is unique
			if(checkGroundLayer()){
				trace(checkGroundLayer());
				return;
			}
			
			
			initParsing();
		}
		

		
		
		/** 
		 * This function loops on tileMaps and then create the game with
		 *
		 * returns 	nothing
		 * */
		private function initParsing():void {
		
			// alpha sorting (for a frame deep management)
			var tileNames:Array = [];
			for each (var info:Object in Registry.tileInfos) 
				if(info.type != 'ground') tileNames.push(info.name);
				else var groundName:String= info.name;
			tileNames.sort();
			tileNames.unshift(groundName);

			
			// finaly loop on tiles
			for each(var name:String in tileNames) {
				tileInfo = Registry.tileInfos[name];
				tileMap = new MyFlxTilemap;
		
				// tilesheet is undefined
				if(!tileInfo.tileSheet) {
					trace('ALERTE : tileSheet n\'est pas défini pour le calque', tileInfo.name);
					tileInfo.tileSheet = (new Registry.blankTilesPNG).bitmapData;
				}
				
				// tileMap is undefined
				if(!tileInfo.tileMap) {
					trace('ALERTE : tileMap n\'est pas défini pour le calque', tileInfo.name);
					tileInfo.tileMap = String(new Registry.blankLevel);
				}
				
				// tileSize is undefined
				if(!tileInfo.tileSize) {
					trace('ALERTE : tileSize n\'est pas défini pour le calque', tileInfo.name);
					tileInfo.tileSize = new Array(50,50);
				}
			
				tileMap.loadMapWithBitmap(tileInfo.tileMap, tileInfo.tileSheet, tileInfo.tileSize[0], tileInfo.tileSize[1]);
				tileMap.scrollFactor.x = tileInfo.scrollFactor ? tileInfo.scrollFactor : 1;
				
				
				// add remove colliding to the defined crossingTiles
				
				
				
				switch(tileInfo.type) {
					case 'ground':
						ground = tileMap;
						tileSize = tileInfo.tileSize;
						Registry.solidTilesPool.add(ground);
						
						if(Registry.gameInfos.world.crossingTiles) {
							for each (var tileID:uint in Registry.gameInfos.world.crossingTiles)
								ground.setTileProperties(tileID, FlxObject.NONE);
						}
					break;
					case 'background' : 
						backgrounds.add(tileMap);
						break;
					case 'firstground':
						firstgrounds.add(tileMap);
						break;
					
					case 'dynamic':
						parseDynamicMap(tileInfo);
						break;
					case 'enemy':
						parseEnemyMap(tileInfo);
						break;
					default:
						trace('no tilemap type found : ', tileInfo.type);
				}
			}
		}
		
		
		private function parseEnemyMap(mapInfos:Object):void {
			
			for each (var entity:Object in Registry.entityInfos){ //looking for Entities to place
				if(entity['type'] != 'player'){
					var infos:Object = entity;
					var coord:Array = tileMap.getTileCoords(entity['tile'].tileID ,false);
					
					for each (var pos:FlxPoint in coord){ // find entities in the map
						switch (infos.type) { //place entities
							case 'AI_simple':
								new Enemy(pos.x, pos.y, infos );
								break;
							case 'AI_boss':
								new Boss(pos.x, pos.y, infos);
								break
							case 'AI_minion' : 
								break;
							default:
								trace('no enemy type found : ', infos.type);
								break;
						}
					}
				}
			}
		}
		
		
		private function parseDynamicMap(mapInfos:Object):void {
			for each (var infos:Object in Registry.blockInfos) { //  scan the blocList
				for each (var tileID:uint in infos.tileID) { //  find IDs in the blocList
					if (mapInfos.tileMap.indexOf(infos.tileID) != -1) { // then find IDs in the map given
						var pos:Array = tileMap.getTileCoords(infos.tileID, false); //  finaly place the tiles
						infos.tileID = tileID;
						for each (var coord:FlxPoint in pos) {
							switch (infos.type) {
								case 'collect':
									new Collect(coord.x, coord.y, infos, mapInfos.name);
									break;
								case 'trigger':
									new Trigger(coord.x, coord.y, infos, mapInfos.name);
									break;
								case 'trap':
									new Trap(coord.x, coord.y, infos, mapInfos.name);
								case 'destructible':
									new Destructible(coord.x, coord.y, infos, mapInfos.name);
									break;
								case 'door':
									new Door(coord.x, coord.y, infos, mapInfos.name);
									break;
								case 'stalling': //deprecated
								case 'fallingTrap':
									new FallingTrap(coord.x, coord.y, infos, mapInfos.name);
									break;
								case 'pendulum':
									new Pendulum(coord.x, coord.y, infos, mapInfos.name);
									break;
								case 'collapse':
									new Collapse(coord.x, coord.y, infos, mapInfos.name);
									break;
								case 'checkpoint':
									this.checkpoints.push(new Checkpoint(coord.x, coord.y, infos, mapInfos.name));
									break;
								default:
									trace('no block type found', infos.type);
							}
						}
					}
				}
			}
		}
		
		
		/** 
		 * This methods tells if there none or much more than one "ground" type layer
		 * returns	string
		 * */
		private function checkGroundLayer():String{
			var check:Boolean;
			var msg:String;
			
			for each(var layer:Object in Registry.tileInfos){
				if(layer.type == "ground"){
					if(!check) check = true;	
					else msg = "ALERTE : il ne doit y avoir qu'un seul calque de type \'ground\'";
				}
			}
			if(!check) msg ="ALERTE : un calque de type \'ground\' est requis";
			return msg;
		}
		
		
	}
}
